﻿using System;
using System.Security.Cryptography;
using System.Text;
using ZL.Web.Utility.Config;

namespace ZL.Web.Utility
{
    public class ConfContent
    {
        public static string EncryptToBase64Format(string sPlaintext, string sKey)
        {
            string sMD5 = getMd5Hash(sKey + sPlaintext);    //生成16字节MD5码
            //Console.WriteLine("sMD5: " + sMD5);
            byte[] bytMD5 = new byte[16];
            //将md5结果值放入字节数组
            for (int i = 0; i <= 15; i++)
            {
                bytMD5[i] = Convert.ToByte(sMD5.Substring(2 * i, 2), 16);
            }

            byte[] bytKey = Encoding.ASCII.GetBytes(sKey);  //密码放入字节数组
            long lLenKey = bytKey.LongLength;

            byte[] bytPlainttext = Encoding.Default.GetBytes(sPlaintext); //明文放入字节数组
            long lLenPlaintext = bytPlainttext.LongLength;

            byte[] byt = new byte[16 + lLenKey + lLenPlaintext];
            Array.Copy(bytMD5, 0, byt, 0, bytMD5.Length);                   //向目标中放入MD5码，起始位置：0
            Array.Copy(bytKey, 0, byt, bytMD5.Length, lLenKey);             //向目标中放入密码，起始位置：bytMD5.length
            Array.Copy(bytPlainttext, 0, byt, 16 + bytKey.Length, lLenPlaintext); //向目标中放入明文, 起始位置：16 + bytKey.Length

            for (long i = 0; i < byt.LongLength; i++)
            {
                byt[i] = (byte)(byt[i] ^ bytKey[i % lLenKey]);  //用密码加密
            }

            Random rd = new Random();
            byte[] bytRndKey = new byte[4];
            //bytRndKey[0] = (byte)((63 - 0 + 1) * rd.Next());
            //bytRndKey[1] = (byte)((63 - 0 + 1) * rd.Next());
            //bytRndKey[2] = (byte)((63 - 0 + 1) * rd.Next());
            //bytRndKey[3] = (byte)((63 - 0 + 1) * rd.Next());
            rd.NextBytes(bytRndKey);            //生成随机数

            for (long i = 0; i < byt.LongLength; i++)
            {
                byt[i] = (byte)(byt[i] ^ bytRndKey[i % 4]);  //用随机数加密
            }

            byte[] bytCiphertext = new byte[4 + 16 + lLenKey + lLenPlaintext];
            Array.Copy(bytRndKey, bytCiphertext, 4);
            Array.Copy(byt, 0, bytCiphertext, 4, 16 + lLenKey + lLenPlaintext);

            return Convert.ToBase64String(bytCiphertext);
        }

        //处理小写英文字母、数字及~!@#$%^&*()_+?，不含大写字母
        public static string EncryptPass(string ResStr)
        {
            string Key = "àèéêìíóùúüèóòùà";
            int intEncrypted;
            string Result = "";
            if (ResStr.Length > 0)
            {
                for (int i = 0; i < ResStr.Length; i++)
                {
                    char Orig = ResStr[i];                                      //取源串的一个字符      
                    char cKey = Key[(i + 1) % Key.Length];                      //取密钥的一个字符
                    int intOrig = ASC(ResStr.Substring(i, 1));                  //取源串一个字符的ascii码
                    int intKey = ASC(Key.Substring((i + 1) % Key.Length, 1));   //取密码一个字符的ascii码，循环取
                    intEncrypted = intOrig ^ intKey;
                    //针对双字节的处理，加密时用到
                    if (intEncrypted < 0)
                    {
                        intEncrypted += 65536;
                        byte[] byt = new byte[2];
                        byt[0] = (byte)(intEncrypted / 256);
                        byt[1] = (byte)(intEncrypted ^ 256);
                        Result += System.Text.Encoding.GetEncoding("GB2312").GetString(byt);
                    }
                    else
                    {
                        Result += ((char)intEncrypted).ToString();
                    }
                }
                return Result;
                //For i = 1 To Len(ResStr)
                //    txtOrig = Mid(ResStr, i, 1)
                //    txtKey = Mid(Key, (i Mod Len(Key)) + 1)
                //    txtEncrypted = Asc(txtOrig) Xor Asc(txtKey)
                //    Result = Result & Chr(txtEncrypted)
                //Next i
                //EncryptPass = Result

            }
            else
            {
                return Result;
            }
        }

        //获取ASC码，此算法得到的结果与vb6中的ASC函数的结果相同
        private static int ASC(String Data)
        {
            byte[] b = System.Text.Encoding.Default.GetBytes(Data);
            int p = 0;

            if (b.Length == 1) //如果为英文字符直接返回
                return (int)b[0];
            for (int i = 0; i < b.Length; i += 2)
            {
                p = (int)b[i];
                p = p * 256 + b[i + 1] - 65536;
            }
            return p;
        }

        //public static ZLConfig LoadconfigValue()
        //{
        //    XDocument doc = XDocument.Load(HttpContext.Current.Server.MapPath("~/App_Data/Config.xml"));
        //    var query = from p in doc.Elements("properties").Elements("property")
        //                let nElement = p.Element("TenPayV3Model")
        //        where nElement != null
        //        let xElement = p.Element("ChargeTemplateId")
        //        where xElement != null
        //        let eElement = p.Element("PayTemplateId")
        //        where eElement != null
        //        let pElement = p.Element("SMSAccount")
        //        where pElement != null
        //        let daElement = p.Element("SMSPwd")
        //        where daElement != null
        //        let uElement = p.Element("SMSurl")
        //        where pElement != null
        //        let wElement = p.Element("WeixinEncodingAESKey")
        //        where wElement != null
        //        let tement = p.Element("WeixinToken")
        //        where tement != null
        //        let Coutement = p.Element("Couserab")
        //        where Coutement != null
        //                let Regtement = p.Element("RegesiterUrl")
        //                where Regtement != null
        //                select new ZLConfig()
        //        {
        //            TenPayV3Model = nElement.Value,
        //            ChargeTemplateId = xElement.Value,
        //            PayTemplateId = eElement.Value,
        //            SMSAccount = pElement.Value,
        //            SMSPwd = daElement.Value,
        //            SMSurl = uElement.Value,
        //            WeixinEncodingAESKey = wElement.Value,
        //            WeixinToken = tement.Value,
        //            RegesiterUrl = Regtement.Value
        //        };
        //    return query.FirstOrDefault();
        //}

        public static string DecryptFromBase64Formatstr(string sCiphertext, string sKey)
        {
            //Console.WriteLine(sCiphertext);
            var bytKey = Encoding.ASCII.GetBytes(sKey);
            long lLenKey = bytKey.LongLength;

            byte[] bytCiphertext = Convert.FromBase64String(sCiphertext); //密文base64解码
            long lLenPlaintext = bytCiphertext.LongLength + 1 - 4 - 16 - lLenKey; //取明文长度            

            byte[] bytRndKey = new byte[4];
            Array.Copy(bytCiphertext, 0, bytRndKey, 0, 4); //取密文的前四个字节放在bytRndKey中            

            //取密文的其余部分放在byt中,跳过前四个字节
            byte[] byt = new byte[16 + lLenKey + lLenPlaintext - 1];
            Array.Copy(bytCiphertext, 4, byt, 0, 16 + lLenKey + lLenPlaintext - 1);

            for (long i = 0; i < byt.LongLength; i++)
            {
                byt[i] = (byte)(byt[i] ^ bytRndKey[i % 4]); //第一次解密，用密文中自带的密码
            }

            for (long i = 0; i < byt.LongLength; i++)
            {
                byt[i] = (byte)(byt[i] ^ bytKey[i % lLenKey]); //第二次解密，用传入的密码
            }
            //Console.WriteLine("byt: " + System.Text.Encoding.ASCII.GetString(byt));

            StringBuilder sbMD5 = new StringBuilder(40); //取出MD5码，用于校验
            for (long i = 0; i < 16; i++)
            {
                sbMD5.Append(byt[i].ToString("x2"));
            }

            byte[] sKeySrc = new byte[lLenKey];
            Array.Copy(byt, 16, sKeySrc, 0, lLenKey); //取出密码，开始于第16字节   
            string strKeySrc = System.Text.Encoding.ASCII.GetString(sKeySrc); //密码转为字符串            

            byte[] sPlaintext = new byte[lLenPlaintext - 1];
            Array.Copy(byt, 16 + lLenKey, sPlaintext, 0, lLenPlaintext - 1); //取出解密后的明文，在MD5码和密码之后
            string strPlaintext = System.Text.Encoding.Default.GetString(sPlaintext);
            return strPlaintext;
        }


        #region 支付宝参数解密
        public static TenPayV3Model DecryptFromBase64Format(string sCiphertext, string sKey)
        {
            //Console.WriteLine(sCiphertext);
            var bytKey = Encoding.ASCII.GetBytes(sKey);
            long lLenKey = bytKey.LongLength;

            byte[] bytCiphertext = Convert.FromBase64String(sCiphertext);           //密文base64解码
            long lLenPlaintext = bytCiphertext.LongLength + 1 - 4 - 16 - lLenKey;   //取明文长度            

            byte[] bytRndKey = new byte[4];
            Array.Copy(bytCiphertext, 0, bytRndKey, 0, 4);  //取密文的前四个字节放在bytRndKey中            

            //取密文的其余部分放在byt中,跳过前四个字节
            byte[] byt = new byte[16 + lLenKey + lLenPlaintext - 1];
            Array.Copy(bytCiphertext, 4, byt, 0, 16 + lLenKey + lLenPlaintext - 1);

            for (long i = 0; i < byt.LongLength; i++)
            {
                byt[i] = (byte)(byt[i] ^ bytRndKey[i % 4]);     //第一次解密，用密文中自带的密码
            }

            for (long i = 0; i < byt.LongLength; i++)
            {
                byt[i] = (byte)(byt[i] ^ bytKey[i % lLenKey]);  //第二次解密，用传入的密码
            }
            //Console.WriteLine("byt: " + System.Text.Encoding.ASCII.GetString(byt));

            StringBuilder sbMD5 = new StringBuilder(40);    //取出MD5码，用于校验
            for (long i = 0; i < 16; i++)
            {
                sbMD5.Append(byt[i].ToString("x2"));
            }

            byte[] sKeySrc = new byte[lLenKey];
            Array.Copy(byt, 16, sKeySrc, 0, lLenKey);                           //取出密码，开始于第16字节   
            string strKeySrc = System.Text.Encoding.ASCII.GetString(sKeySrc);   //密码转为字符串            

            byte[] sPlaintext = new byte[lLenPlaintext - 1];
            Array.Copy(byt, 16 + lLenKey, sPlaintext, 0, lLenPlaintext - 1);            //取出解密后的明文，在MD5码和密码之后
            string strPlaintext = System.Text.Encoding.Default.GetString(sPlaintext);   //解密后的明文转为字符串
            //Console.WriteLine("sPlaintext: " + strPlaintext);
            //string strUPlaintext = System.Text.Encoding.UTF8.GetString(sPlaintext);
            //Console.WriteLine("strUPlaintext: " + strUPlaintext);

            //校验明文
            //if (!verifyMd5Hash(strKeySrc + strPlaintext, sbMD5.ToString()))
            //{
            //    throw new Exception("发生异常：解密结果文本的MD5码校验失败。");
            //}

            string[] arrConf;
            arrConf = strPlaintext.Split((char)127);                     //拆分明文，分隔符为：(char)127


            if ((arrConf.Length != 12))
            {
                throw new Exception("发生异常：解密结果文本中的字段数量错误。");
            }


            TenPayV3Model weixinpay = new TenPayV3Model();
            weixinpay.regcode_ = arrConf[0].ToString();
            weixinpay.corpname_j = arrConf[1].ToString();
            weixinpay.appid_j = arrConf[2].ToString();
            //weixinpay.appid_j = "wx0b675b8df0ce0f8d";
            //weixinpay.timeout_j = arrConf[2].ToString();
            weixinpay.mch_id = arrConf[3].ToString();
            weixinpay.subappid_j = arrConf[4].ToString();
            weixinpay.submch_id = arrConf[5].ToString();
            if (!string.IsNullOrEmpty(weixinpay.subappid_j) && !string.IsNullOrEmpty(weixinpay.submch_id))
            {
                weixinpay.Mode = mchType.特约商户;
            }
            else
            {
                weixinpay.Mode = mchType.普通商户;
            }
            weixinpay.publicKey_j = arrConf[6].ToString();
            weixinpay.Sslcert = arrConf[7].ToString();
            weixinpay.SslcertPassword = arrConf[8].ToString();
            weixinpay.PostUrl = arrConf[9].ToString();
           
            //weixinpay.AppSecret = arrConf[10].ToString();
            //weixinpay.AppSecret = "2e135de9ceed8f009f88ddb536492200";
            return weixinpay;
        }

        // Hash an input string and return the hash as
        // a 32 character hexadecimal string.
        private static string getMd5Hash(string input)
        {
            // Create a new instance of the MD5CryptoServiceProvider object.
            MD5 md5Hasher = MD5.Create();

            // Convert the input string to a byte array and compute the hash.
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));

            StringBuilder sBuilder = new StringBuilder();

            // Loop through each byte of the hashed data 
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            // Return the hexadecimal string.
            return sBuilder.ToString();
        }

        // Verify a hash against a string.
        private static bool verifyMd5Hash(string input, string hash)
        {
            // Hash the input.
            string hashOfInput = getMd5Hash(input);

            // Create a StringComparer an compare the hashes.
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;

            if (0 == comparer.Compare(hashOfInput, hash))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion
    }
}
